package yunjiao.javatutorials.guava.concurrent.interrupt;

import yunjiao.javatutorials.guava.concurrent.ForwardingCondition;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;

/**
 * 带中断处理的 Condition
 *
 * @author yangyunjiao
 */
public class InterruptAwareCondition extends ForwardingCondition {
    private final Condition delegate;
    private final AtomicBoolean wasInterrupted = new AtomicBoolean(false);
    private final AtomicInteger interruptCount = new AtomicInteger(0);

    public InterruptAwareCondition(Condition delegate) {
        this.delegate = delegate;
    }

    @Override
    protected Condition delegate() {
        return delegate;
    }

    @Override
    public void await() throws InterruptedException {
        wasInterrupted.set(false);
        try {
            super.await();
        } catch (InterruptedException e) {
            wasInterrupted.set(true);
            interruptCount.incrementAndGet();
            System.out.println("[InterruptAwareCondition] 等待被中断");
            throw e;
        }
    }

    @Override
    public boolean await(long time, TimeUnit unit) throws InterruptedException {
        wasInterrupted.set(false);
        try {
            return super.await(time, unit);
        } catch (InterruptedException e) {
            wasInterrupted.set(true);
            interruptCount.incrementAndGet();
            System.out.println("[InterruptAwareCondition] 带超时的等待被中断");
            throw e;
        }
    }

    @Override
    public long awaitNanos(long nanosTimeout) throws InterruptedException {
        wasInterrupted.set(false);
        try {
            return super.awaitNanos(nanosTimeout);
        } catch (InterruptedException e) {
            wasInterrupted.set(true);
            interruptCount.incrementAndGet();
            System.out.println("[InterruptAwareCondition] 纳秒级等待被中断");
            throw e;
        }
    }

    @Override
    public void awaitUninterruptibly() {
        wasInterrupted.set(false);

        // 保存当前中断状态
        boolean interrupted = Thread.interrupted();
        if (interrupted) {
            wasInterrupted.set(true);
            interruptCount.incrementAndGet();
            System.out.println("[InterruptAwareCondition] 不可中断等待前线程已被中断");
        }

        try {
            super.awaitUninterruptibly();
        } finally {
            // 恢复中断状态
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public boolean awaitUninterruptibly(long time, TimeUnit unit) {
        wasInterrupted.set(false);

        // 保存当前中断状态
        boolean interrupted = Thread.interrupted();
        if (interrupted) {
            wasInterrupted.set(true);
            interruptCount.incrementAndGet();
            System.out.println("[InterruptAwareCondition] 带超时的不可中断等待前线程已被中断");
        }

        try {
            long nanosTimeout = unit.toNanos(time);
            long deadline = System.nanoTime() + nanosTimeout;

            while (true) {
                try {
                    return awaitNanos(nanosTimeout) > 0;
                } catch (InterruptedException e) {
                    // 在不可中断模式下，我们忽略中断但记录它
                    wasInterrupted.set(true);
                    interruptCount.incrementAndGet();
                    nanosTimeout = deadline - System.nanoTime();
                    if (nanosTimeout <= 0L) {
                        return false;
                    }
                }
            }
        } finally {
            // 恢复中断状态
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

    // 状态查询方法
    public boolean wasInterrupted() {
        return wasInterrupted.get();
    }

    public int getInterruptCount() {
        return interruptCount.get();
    }

    public void clearInterruptFlag() {
        wasInterrupted.set(false);
        System.out.println("[InterruptAwareCondition] 中断标志已清除");
    }

    public void resetStatistics() {
        interruptCount.set(0);
        wasInterrupted.set(false);
        System.out.println("[InterruptAwareCondition] 统计信息已重置");
    }

    public void printInterruptStatistics() {
        System.out.println("=== InterruptAwareCondition 中断统计 ===");
        System.out.println("总中断次数: " + getInterruptCount());
        System.out.println("当前中断标志: " + wasInterrupted());
    }
}
